﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace APIMon
{
    class ProgramStartDescription
    {
        /// <summary>
        /// Path to the program image directory
        /// </summary>
        private string _image_dir=string.Empty;
        public string image_dir
        {
            get { return _image_dir; }
            set { _image_dir = Path.GetFullPath(value); }
        }
        /// <summary>
        /// Filename of the program image
        /// </summary>
        private string _image_filename = string.Empty;
        public string image_filename
        {
            get { return _image_filename; }
            set {
				if (File.Exists(Path.Combine(image_dir, value))) {
					_image_filename = value;
				} else {
					throw new FileNotFoundException("File not found: "+Path.Combine(image_dir, value));
				}
            }
        }

		//public string[] images_filenames {
		//    get {
		//        return getExecutables(_image_dir);
		//    }
		//}

        public string image_path{
            get { return Path.Combine(_image_dir, _image_filename); }
        }

        /// <summary>
        /// Command line provide to the program
        /// </summary>
        public string command_line = string.Empty;

        /// <summary>
        /// Maximum running time for that program in seconds
        /// </summary>
        public int max_running_time=10;
        public ProgramStartDescription(){

        }

		/// <summary>
		/// Copying constructor
		/// </summary>
		/// <param name="prev"></param>
        public ProgramStartDescription(ProgramStartDescription prev){
            _image_dir = prev._image_dir;
            _image_filename = prev._image_filename;
			max_running_time = prev.max_running_time;
        }

		public string[] getExecutables() {
			return getExecutables(_image_dir);
		}

		/// <summary>
		/// Returns list of executables (exe files) in the directory specified
		/// </summary>
		/// <param name="path">directory to look fro executables</param>
		/// <returns></returns>
        public static string[] getExecutables(string path){
            return Directory.GetFiles(path, "*.exe", SearchOption.TopDirectoryOnly);
        }

		/// <summary>
		/// Creates new program description with different command line parameters. The rest is kept the same
		/// </summary>
		/// <param name="command_line">newe command line parameters for the program</param>
		/// <returns></returns>
        public ProgramStartDescription useDifferentCommandLine(string command_line){
            ProgramStartDescription result = new ProgramStartDescription(this);
            result.command_line = command_line;
            return result;
        }


		/// <summary>
		/// Creates new program description with different executable. The rest is kept the same
		/// </summary>
		/// <param name="image_file_name">image file name</param>
		/// <returns></returns>
		public ProgramStartDescription useDifferentImageFile(string image_file_name) {
			ProgramStartDescription result = new ProgramStartDescription(this);
			result.image_filename = image_file_name;
			return result;
		}

		/// <summary>
		/// This operation creates new program description on the basis of provided one with changed command line parameters
		/// </summary>
		/// <param name="a">program start desription to inherit from</param>
		/// <param name="new_params">new command line paramters for the program</param>
		/// <returns></returns>
        public static ProgramStartList operator +(ProgramStartDescription a, string new_params){
           ProgramStartList result = new ProgramStartList();
            result.Add (a);
            result.Add(a.useDifferentCommandLine(new_params));
            return result;
        }

		public override string ToString() {
			string result = string.Empty;
			result += image_path + command_line + "|| max_running_time=" + max_running_time;
			return result;
		}
    }

    class ProgramStartList: List<ProgramStartDescription>{

        public ProgramStartDescription last(){
            if (this.Count==0){
                this.Add(new ProgramStartDescription());
            }
            return this.Last();
        }

        public static ProgramStartList operator +(ProgramStartList i, string new_params)
        {
            i.Add(i.Last().useDifferentCommandLine(new_params));
            return i;
        }

        public static ProgramStartList operator +(ProgramStartList i, ProgramStartDescription new_program)
        {
            i.Add(new_program);
            return i;
        }

		public static ProgramStartList operator +(ProgramStartList i, string[] program_names) {
			foreach (string image_name in program_names) {
				i.Add(i.Last().useDifferentImageFile(image_name));
			}
			return i;
		}
    }
}
